#include <iostream>
#include <unordered_map>
#include <list>
using namespace std;


/*********************************************************************************************
 *  行为型模式：主要关注对象之间的通信
 *  观察者(监听者)模式(发布-订阅模式)：主要关注对象的一对多的关系，也就是多个对象都依赖一个对象，
 *                                  当该对象的状态发生改变时，其它对象都能够接收到相应的通知。
 *  例如，曲线图(对象1) 柱状图(对象2) 圆饼图(对象3) 都依赖于==》 一组数据(数据对象)
 *       数据改变，这多个对象应该及时收到通知
 * 
 *  Observerl  Observer2  Observer3
 *  Subiect(主题) 有更改，应该及时通知相应的观察者，去处理相应的事件
 * 
 */


class Observer
{
public:
    virtual void handle(int msgid) = 0;
};

class Observer1 : public Observer
{
public:
    void handle(int msgid)
    {
        switch (msgid)
        {
        case 1:
            cout << "Observer1 recv 1 msg!\n";
            break;
        case 2:
            cout << "Observer1 recv 2 msg!\n";
            break;
        default:
            cout << "Observer1 recv unknow msg!\n";
            break;
        }
    }
};

class Observer2 : public Observer
{
public:
    void handle(int msgid)
    {
        switch (msgid)
        {
        case 2:
            cout << "Observer2 recv 2 msg!\n";
            break;
        default:
            cout << "Observer2 recv unknow msg!\n";
            break;
        }
    }
};

class Observer3 : public Observer
{
public:
    void handle(int msgid)
    {
        switch (msgid)
        {
        case 1:
            cout << "Observer3 recv 1 msg!\n";
            break;
        case 3:
            cout << "Observer3 recv 3 msg!\n";
            break;
        default:
            cout << "Observer3 recv unknow msg!\n";
            break;
        }
    }
};

class Subject 
{
public:
    // 给主题增加观察者对象
    void addObserver(Observer* obs, int msgid)
    {
        // _submap[msgid].push_back(obs);

        auto it = _submap.find(msgid);
        if(it != _submap.end()) it->second.push_back(obs);
        else 
        {
            list<Observer*> lt;
            lt.push_back(obs);
            _submap.emplace(msgid, lt);
        }
    }
    // 主题改变，通知观察者
    void dispatch(int msgid)
    {
        auto it = _submap.find(msgid);
        if(it != _submap.end())
        {
            for(Observer* obs : it->second)
                obs->handle(msgid);
        }
    }
private:
    unordered_map<int, list<Observer*>> _submap;
};

int main()
{
    Observer1 *p1 = new Observer1();
    Observer2 *p2 = new Observer2();
    Observer3 *p3 = new Observer3();
    
    Subject subject;
    subject.addObserver(p1, 1);
    subject.addObserver(p1, 2);
    subject.addObserver(p2, 2);
    subject.addObserver(p3, 1);
    subject.addObserver(p3, 3);

    int msgid = 0;
    for(;;)
    {
        cin >> msgid;
        if(msgid == 0) break;
        subject.dispatch(msgid); 
    }
    return 0;
}